package com.kuang.common.generator.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 生成分布式ID
 */
@Service
public class GeneratorIdServiceImpl implements IGeneratorIdService {

    @Autowired
    private RedisTemplate redisTemplate;
    // 用于控制计数器达到最大长度以后进行递增，如果没就在前面补0
    static final int DEFAULT_LENGTH = 6;

    /**
     *
     * @param key 代表是：不同业务id
     * @return
     */
    public long genUid(String key) {
        return redisTemplate.opsForValue().increment(key);
    }


    /**
     * 流水号生成
     * 获取唯一序列号，每天递增1，超过一天重置成0
     * 格式：yyyyMMdd000000 得到的结构：202108180000001,202108180000002.....20210818999999
     * 如果超过6位：2021081810000000 2021081810000001
     *
     * @return
     */
    public String getSequence(String key) {
        // 1： 时间前缀
        String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // 2：redis递增获取每天的递增数量
        Long num = this.genIncrementAndExpire(key+ currentDate);
        // 3：获取递增长度，是否小于DEFAULT_LENGTH 如果小于就前面补零。如果大于就递增即可
        String str = String.valueOf(num);
        // 4：补零操作
        int len = str.length();
        // 4-1：是否小于DEFAULT_LENGTH 如果小于就前面补零。如果大于就递增即可
        StringBuilder sb = new StringBuilder();
        // 5：添加时间
        sb.append(currentDate);
        if (len >= DEFAULT_LENGTH) {
            sb.append(str);
            return sb.toString();
        }
        int rest = DEFAULT_LENGTH - len;
        for (int i = 0; i < rest; i++) {
            sb.append('0');
        }
        sb.append(str);
        // 6： 时间+补零操作返回订单流水号
        return sb.toString();
    }


    /**
     * @return java.lang.Long
     * @Author 徐柯
     * @Description 生成全局id
     * @Date 18:50 2021/5/20
     * @Param []
     **/
    private long genIncrementAndExpire(String key) {
        // 不存在准备创建 键值对
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());//0
        // 计数器累加
        Long counter = entityIdCounter.incrementAndGet();
        if ((null == counter || counter.longValue() == 1)) {// 初始设置过期时间
            // 设置清除的目的，是让每天的计数器都从0开始
            entityIdCounter.expire(1, TimeUnit.DAYS);// 单位天
        }
        return counter;
    }

}